#ifndef F_CPU
#define F_CPU 16000000UL
#endif

#include "rot_serial.h"

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <string.h>

volatile char msg_rx[SERIAL_BUF_SIZE];
volatile char msg_tx[SERIAL_BUF_SIZE];
volatile uint8_t rx_buf_pos;
volatile uint8_t tx_buf_pos;
volatile uint8_t serial_rx;

ISR(USART_RX_vect) {
  msg_rx[rx_buf_pos++] = UDR0;
  if (rx_buf_pos==SERIAL_BUF_SIZE-1) rx_buf_pos=0;
  if (serial_rx==0) serial_rx = 1;
}

ISR(USART_UDRE_vect) {
  if (msg_tx[tx_buf_pos] != '\0') {
    UDR0 = msg_tx[tx_buf_pos++];
  }
  else {
    UCSR0B &= ~(1 << UDRIE0);
    tx_buf_pos = 0;
  }
}

void serial_init(unsigned int bittimer)
{
  /* Set the baud rate */
  UBRR0H = (unsigned char) (bittimer >> 8);
  UBRR0L = (unsigned char) bittimer;
  /* Set the framing to 8N1 */
  UCSR0C = (3 << UCSZ00);
  /* Enable RX Interrupt and Engage!*/
  UCSR0B = (1 << RXCIE0) | (1 << RXEN0) | (1 << TXEN0);
  /* Initialize Serial Receiver Variables */
  serial_rx = 0;
  tx_buf_pos = 0;
  rx_buf_pos = 0;
}

void serial_transmit(char* msg)
{
  strcpy((char*) msg_tx,msg);
  tx_buf_pos = 0;
  UCSR0B |= (1 << UDRIE0);
}

void serial_write(unsigned char c)
{
  while ( !(UCSR0A & (1 << UDRE0)) );

  UDR0 = c;
}

unsigned char serial_read(void)
{
  while( !(UCSR0A & (1 << RXC0)) );

  return UDR0;
}
